package vertxZeebe.jobworker;

import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.zeebe.client.api.response.ActivatedJob;
import io.zeebe.client.api.worker.JobClient;
import io.zeebe.client.api.worker.JobHandler;
import vertxZeebe.service.PgService;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.*;

public class HumanTaskJobWorker implements JobHandler {

    static List<String> SUPPORTED_FIELD_TYPES = Arrays.asList("string", "number", "boolean");
    Map<String, String> taskFormMap = new HashMap<>();
    PgService pgService;

    public HumanTaskJobWorker(PgService pgService) {
        this.pgService = pgService;
        taskFormMap.put("custom-task-form", getTaskForm("/html/custom-task-form.html"));
        taskFormMap.put("default-task-form", getTaskForm("/html/default-task-form.html"));
    }

    @Override
    public void handle(JobClient client, ActivatedJob job) {
        Map<String, String> customHeaders = job.getCustomHeaders();

        Long workflowInstanceKey = job.getWorkflowInstanceKey();
        Long jobKey = job.getKey();
        String name = customHeaders.getOrDefault("name", job.getElementId());
        String description = customHeaders.getOrDefault("description", "");
        String variables = job.getVariables();
        //映射关系，解析页面模版内容----这里可以从文件服务器获取页面模版
        String taskForm = taskFormMap.get(customHeaders.get("taskForm"));

        String formFields = null;
        try {
            formFields = customHeaders.get("formFields");
            validateFormFields(formFields);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Long assignee = Long.valueOf(customHeaders.getOrDefault("assignee", "-1"));
        String candidateGroup = customHeaders.getOrDefault("candidateGroup","");

        //设置截止时间
        String duration = customHeaders.getOrDefault("duration", "1D");
        String symbol = duration.substring(duration.length() - 1);
        Long number = Long.valueOf(duration.replace(symbol, ""));
        Instant instance = Instant.now();
        switch (symbol) {
            case "Y":
                instance = instance.plus(number, ChronoUnit.YEARS);
                break;
            case "M":
                instance = instance.plus(number, ChronoUnit.MONTHS);
                break;
            case "D":
                instance = instance.plus(number, ChronoUnit.DAYS);
                break;
            case "h":
                instance = instance.plus(number, ChronoUnit.HOURS);
                break;
            case "m":
                instance = instance.plus(number, ChronoUnit.MINUTES);
                break;
            case "s":
                instance = instance.plus(number, ChronoUnit.SECONDS);
                break;
            default:
                throw new RuntimeException("人工任务的日期格式不正确");
        }
        ;
        OffsetDateTime offsetDateTime = OffsetDateTime.ofInstant(Instant.ofEpochSecond(instance.getEpochSecond()), ZoneOffset.UTC);


        //将人工任务存入task表，表示任务的基本信息
        pgService.saveTask(workflowInstanceKey, jobKey, name, description, variables, taskForm, formFields, assignee, candidateGroup, offsetDateTime).setHandler(v->{
            if(v.succeeded()){
                //当任务被分配或者声明时到具体的某一个人时，将任务添加到task_claim表
                if (assignee != -1) {
                    pgService.saveTaskClaim(workflowInstanceKey, jobKey, assignee, offsetDateTime).setHandler(v2->{
                        if(v2.succeeded()){
                            System.out.println(String.format("saveTaskClaim(%s)方法执行完成",jobKey));
                        }else{
                            System.out.println(String.format("saveTaskClaim(%s)方法执行失败",jobKey));
                        }

                    });
                }else{
                    System.out.println(jobKey+"人工任务尚未分配到个人");
                }
            }
        });
    }

    private void validateFormFields(String form) {
        JsonArray formFields = new JsonArray(form);

        formFields.forEach(field -> {
            if (((JsonObject) field).getString("key") == null) {
                throw new RuntimeException("form-field must have a 'key'");
            }
            String type = ((JsonObject) field).getString("type");
            if (!SUPPORTED_FIELD_TYPES.contains(type)) {
                throw new RuntimeException(String.format("type of form-field '%s' is not supported. Must be one of: %s", type, SUPPORTED_FIELD_TYPES));
            }
            ;
        });
    }

    private String getTaskForm(String path) {
        try {
            return new String(Files.readAllBytes(Paths.get(getClass().getResource(path).toURI())));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
